<script setup name="CustomUploadsize">
import { reactive, defineProps, ref, watch, defineEmits } from "vue";
import { debounce } from "lodash-es";

const emit = defineEmits(["update:dialogVisible", "submitSuccess"]);
const _this = reactive({
  dialogVisible: false,
  loading: false,
  loadingTwo: false,
  style: {
    width: 280,
    height: 280,
  },
  imgSrc: "",
  judgeMove: false,
  offsetX: 0,
  offsetY: 0,
  img1: "",
  img2: "",
});

function close() {
  _this.dialogVisible = false;
  emit("update:dialogVisible", false);
}

const imgUpload = ref(null);
const customRef = ref(null);
// 图片上传
const handleChange = () => {
  imgUpload.value.click();
};
// 上传的方法
function upload(event) {
  _this.loading = true;
  getImgBase64(event.target.files[0])
    .then((res) => {
      _this.imgSrc = res;
    })
    .finally(() => {
      event.target.value = "";
      _this.loading = false;
    });
}
// 图片转base64(这里换成你图片上传的方法)
// drwaImage 如果你传入线上的图片地址,可能会出现一些问题,这边推荐使用base64的,
// 等裁剪完成的时候,你再使用你的图片上传的方法
function getImgBase64(file) {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = function (event) {
      resolve(event.target.result);
    };
    reader.readAsDataURL(file);
  });
}

// 监听content元素 滚轮事件
const mousewheel = debounce((e) => {
  let imgWidth =
    customRef.value.offsetWidth ||
    customRef.value.width ||
    customRef.value.clientWidth;
  let imgHeight =
    customRef.value.offsetHeight ||
    customRef.value.height ||
    customRef.value.clientHeight;
  if (e.deltaY > 0) {
    _this.style.width = getNumber(imgWidth - 10);
    _this.style.height = getNumber(imgHeight - 10);
  } else {
    _this.style.width = imgWidth + 10;
    _this.style.height = imgHeight + 10;
  }
}, 100);
function getNumber(val) {
  return val < 0 ? 0 : val;
}
let contentRef = ref(null);
let moveItemRef = ref(null);

function mousedown(e) {
  if (e.which === 1) {
    _this.judgeMove = true;
    _this.offsetX = e.clientX - moveItemRef.value.getBoundingClientRect().left;
    _this.offsetY = e.clientY - moveItemRef.value.getBoundingClientRect().top;
  }
}
function mouseup() {
  _this.judgeMove = false;
}
function mouseout() {
  _this.judgeMove = false;
}
function mousemove(e) {
  if (_this.judgeMove) {
    const x =
      e.clientX - _this.offsetX - contentRef.value.getBoundingClientRect().left;
    const y =
      e.clientY - _this.offsetY - contentRef.value.getBoundingClientRect().top;
    moveItemRef.value.style.left = x + "px";
    moveItemRef.value.style.top = y + "px";
  }
}

// 保存
function saveSubmit() {
  if (_this.imgSrc === "") {
    // return ElMessage.error("请上传图片");
    console.log("请上传图片");
    return;
  }
  try {
    _this.loadingTwo = true;
    CroppingImage((e) => {
      console.log(e);
    });
  } catch (err) {
    _this.loadingTwo = false;
  }
}
// 裁剪图片
function CroppingImage(callback) {
  let img = new Image(_this.style.width, _this.style.height);
  img.src = _this.imgSrc;
  img.onload = function () {
    let canvas = document.createElement("canvas");
    canvas.width = 490; // 这里的宽度是就是 class="content" 的宽度
    canvas.height = 280; // 这里的高度就是 class="content" 的高度
    let arr = getOverlap();
    let ctx = canvas.getContext("2d");
    //  这里490 - img.width /2 是让图片居中,因为裁剪的坐标就是根据图片的居中来设置的
    // drwaImage 如果你传入线上的图片地址,可能会出现一些问题,这边推荐使用base64的
    ctx.drawImage(img, (490 - img.width) / 2, 0, img.width, img.height);
    let imageData = ctx.getImageData(...arr);
    const newCanvas = document.createElement("canvas");
    newCanvas.width = imageData.width;
    newCanvas.height = imageData.height;
    const newContext = newCanvas.getContext("2d");
    newContext.putImageData(imageData, 0, 0);
    newCanvas.toBlob(function (blob) {
      // 裁剪完成,上传图片
      getImgBase64(blob).then((res) => {
        console.log(res);
        callback(res);
        _this.loadingTwo = false;
      });
    });
  };
}

// 获取重叠的坐标
function getOverlap() {
  const rect1 = contentRef.value.getBoundingClientRect();
  const rect2 = moveItemRef.value.getBoundingClientRect();
  // 计算重叠区域
  const overlap = {
    left: Math.max(rect1.left, rect2.left),
    right: Math.min(rect1.right, rect2.right),
    top: Math.max(rect1.top, rect2.top),
    bottom: Math.min(rect1.bottom, rect2.bottom),
  };

  // 重叠的宽度
  var overlapWidth = overlap.right - overlap.left;
  // 重叠的高度
  var overlapHeight = overlap.bottom - overlap.top;
  return [
    overlap.left - rect1.left,
    overlap.top - rect1.top,
    overlapWidth,
    overlapHeight,
  ];
}
</script>

<template>
  <div>
    <input ref="imgUpload" v-show="false" @change="upload" type="file" name="file" accept="image/*"
      class="file-input" />
    <div ref="contentRef" class="content" @dragstart.prevent @mousewheel.prevent="mousewheel">
      <div ref="customRef" class="custom-ref" :style="{
        width: _this.style.width + 'px',
        height: _this.style.height + 'px',
      }">
        <img :src="_this.imgSrc" alt="" class="img-100" />
      </div>
      <div ref="moveItemRef" class="move-item" @mousedown="mousedown" @mouseup="mouseup" @mouseout="mouseout"
        @mousemove="mousemove"></div>
    </div>
  </div>
  <span class="dialog-footer">
    <el-button type="primary" @click="handleChange" :loading="_this.loading" class="btn upload-new">
      上传图片
    </el-button>
    <el-button @click="saveSubmit" type="primary" class="btn save" :loading="_this.loadingTwo">
      保存
    </el-button>
    <el-button type="primary" @click="close" class="btn cancel">取消</el-button>
  </span>
</template>

<style lang="scss" scoped>
.content {
  position: relative;
  width: 490px;
  height: 280px;
  background: #d8d8d8;
  margin-bottom: 9px;
  user-select: none;
  overflow: hidden;
  margin: 0 auto 9px;

  .custom-ref {
    margin: 0 auto;
    // border-radius: 50%;
    overflow: hidden;

    .img-100 {
      width: 100%;
      height: 100%;
    }
  }

  .move-item {
    position: absolute;
    top: 40px;
    left: 145px;
    width: 200px;
    height: 200px;
    border: 2px solid #409eff;
    background-color: transparent;

    &:hover {
      cursor: move;
    }
  }
}

.dialog-footer {
  display: flex;
  justify-content: center;
}
</style>